﻿/******************************************************************************
* File description: pipeGraph.h
* Function: 用于计算纯化液体管道的液体流向
* Memo: 大概的思路是基于图结构把液路当成传送带算液体应该往哪跑以及流速（参考幸福工厂里面，那种能合并能劈叉的传送带）。具体的逻辑不要问我，我已经把自己绕进去了。
* Current Version: 1.0.0
* Author: JNN
* Date: 2025-07-01
*  -----
*  Copyright by 博坤生物 .
 *****************************************************************************/


#ifndef PIPEGRAPH_H
#define PIPEGRAPH_H

#include <QVector>
#include <QDebug>
#include <QElapsedTimer>
#include <QColor>

#include "treeNode.h"

#define ABS_MINUS(value)    (value>0 ? (value-1) : (value<0 ? (value+1) : 0))       // 返回保留符号的绝对值-1
#define EDGE(v1, v2)  edgeList[std::min(v1, v2)][std::max(v1, v2)]      // 这是一个用二维数组存的稀疏图 (阿巴阿巴……这块咋没做校验)



class PipeGraph
{
public:

    struct stVertex{
        int idx;
        bool isStart;
        bool isEnd;
        bool emitting;          // 喵叽
        int emittingSpeed = 10;
        int emittingGoodIdx = 1;
        stVertex(int idx, bool isStart, bool isEnd){
            this->idx = idx;
            this->isStart = isStart;
            this->isEnd = isEnd;
            this->emitting = false;
        }
    };

    struct stGoods{     // 传送带上的货物………
        int idx = 9;              // -1代表空的 -2代表多种溶液的混合态
        stGoods(int idx = 9){
            this->idx = idx;
        }
    };

    struct stEdge{
        bool connect;
        bool hasValve;
        bool valveState;
        int speed = 0;
        int enterCount = 0;
        int outCount = 0;
        int length = 0;
        QList<stGoods>  goodLists;
        stEdge(){
            connect = false;
            hasValve = false;
            valveState = false;
        }
    };

    struct stValve{
        int idx;
        int v1;
        int v2;
        bool state;
        stValve(int idx, int v1, int v2){
            this->idx = idx;
            this->v1 = v1;
            this->v2 = v2;
            this->state = false;
        }
        stValve(int idx, int v1, int v2, bool state){
            this->idx = idx;
            this->v1 = v1;
            this->v2 = v2;
            this->state = state;
        }
    };


    PipeGraph();

public:
    void updateValveState(QVector<bool> valveState);
    void setVertexEmitting(int sv, bool state);
    bool isVertexConnect(int v1, int v2);

    QVector<TreeNode*> getLiquidPath();

    // 要不换个Vector类型来放吧……

    // 给外面的获取液路的接口
    QVector<QVector<double>> getLiquidState();
    QVector<int>             getLiquidFlowState();

    /*
     * QVariantList{
     *      QVariantMap{
     *          v1: 1
     *          v2: 2
     *          segment: [0.1, 1, 0.3, 4, .....]
     *      }
     *      QVariantMap{
     *          v1: 1
     *          v2: 2
     *          segment: [0.1, 1, 0.3, 4, .....]
     *      }
     *  }
     *
     */


public:
    void setEdgeConnectState(int v1, int v2, bool state, double length = 0);       // length的单位为mm
    void setEdgeHasValve(int v1, int v2, bool state);
    void setEdgeValveState(int v1, int v2, bool state);
    bool getEdgeState(int v1, int v2);      // 判断一个路是否是通的


    void updateLiquidPath();
    void updateEdgeSpeed();
    void updateEdgeSpeed_recursive(TreeNode* startVertex, double speed);
    void clearEdgeSpeed();
    void clearPipe();
    TreeNode* recursivePath(int v, QVector<bool> &flag);


    void updateGoods();
    void supplyGoods();
    bool moveAllGoods = false;

    QVector<double>                syringeSpeed;    // emit点注射器的速度 (单位：ml/s)
    void changeSyringeSpeed(int idx, double speed);

    double                         diameter = 0.6;        // 管道内径

private:


    int                         vertexNum;
    double                      goodLength = 0.1;        // 一个good的长度(mm)

    QVector<stVertex>           vertexList;
    QVector<QVector<stEdge>>    edgeList;
    QVector<stValve>            valveList;

    // 记录发射点该用什么颜色了
    int                         _emitColor_segNum = 30;
    QVector<double>             _emitColor_curColor;
    QVector<double>             _emitColor_curCount;

    QVector<TreeNode*>          liquidPath;     // 如果path里面只有一个点，表示path被堵塞 (出错了)
    // ......不对，这个Path好像是个树........

    QElapsedTimer*              elapsedTimer = nullptr;            // 管道液体的流速自己开一个Timer计算吧
    qint64                      lastUpdateLiquidTime = 0;



};

#endif // PIPEGRAPH_H
